package runnables;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.file.FileConnection;
import javax.microedition.io.file.FileSystemRegistry;

import net.rim.device.api.i18n.ResourceBundle;
import net.rim.device.api.ui.UiApplication;
import screens.Controller;
import strings.WebcampusResource;
import test.ConnectionCreator;
import util.URLutf8Encoder;
import exceptions.DownloadFailureException;
import exceptions.ExistingDownloadException;

public class DownloadRunnable implements Runnable, Stoppable, WebcampusResource{

	// RESOURCES
	private static ResourceBundle resources = ResourceBundle.getBundle(BUNDLE_ID, BUNDLE_NAME);

	boolean stop = false;
    Object notifyObject = new Object();
    
	// download properties

	String url = Controller.getInstance().getUrl();
	String filename = Controller.getInstance().getFilename();
	long size = Controller.getInstance().getSize();

	public void run() {
        if ( stop ) { return; }
		// create connection
		HttpConnection con;
		// default path: sdcard
		String path = System.getProperty("fileconn.dir.memorycard");
		// check media card availability
		boolean sd_card_present = false;
		String root = null;
		Enumeration e = FileSystemRegistry.listRoots();
		while (e.hasMoreElements()){
			root = (String)e.nextElement();
			if(root.equalsIgnoreCase("sdcard/")){
				sd_card_present = true;
			}   
		}
		if ( stop ) { return; }
		if (!sd_card_present){
			// no sd card
			path = System.getProperty("fileconn.dir.documents");
			System.out.println(resources.getString(DOWNLOAD_NOSDCARD));
		} 
		try {
			String url2 = URLutf8Encoder.encodeUrl(url);
			//con = (HttpConnection) Connector.open(url2,Connector.READ);
//			if (DeviceInfo.isSimulator()){
//				con = (HttpConnection) Connector.open(url2+";deviceside=true",Connector.READ);
//			} else {
				con = (HttpConnection) Connector.open(url2+ConnectionCreator.getConnectionString(),Connector.READ);
			//}
			if ( stop ) { return; }
			con.setRequestMethod(HttpConnection.GET);
			// download
			InputStream is = con.openInputStream();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			int ch;
			long count=1;
			while((ch=is.read())!=-1){
				baos.write(ch);
				count++;
				if ( stop ) { return; }
			}
	        if ( stop ) { return; }
			// check if the whole file was downloaded
			if (count-1!=size){
				throw new DownloadFailureException();
			}
			byte[] dwfile=baos.toByteArray();
			// close
			con.close();
			
			// save
			FileConnection fc;
			fc = (FileConnection) Connector.open(path+filename,Connector.READ_WRITE);
	        if ( stop ) { return; }
			if(!fc.exists()){
				fc.create();
			} else {
				//TODO overwrite o duplicar ?
				throw new ExistingDownloadException();
			}
			OutputStream os = fc.openOutputStream();
	        if ( stop ) { return; }
			os.write(dwfile);
			os.close();
			//TODO
			//
			fc.close();
			// successful download
			Controller.getInstance().setDownloadMessage(resources.getString(DOWNLOAD_SUCCESS)+":\n"+fc.getPath());
		} catch (IOException e1) {
			// unsuccessful download (other errors)
			e1.printStackTrace();
			Controller.getInstance().setDownloadMessage(resources.getString(DOWNLOAD_FAILURE));
			if ( stop ) { return; }
		} catch (ExistingDownloadException e2) {
			e2.printStackTrace();
			System.out.println(e2.getMessage());
			Controller.getInstance().setDownloadMessage(e2.getMessage());
	        if ( stop ) { return; }
		} catch (DownloadFailureException e3) {
			e3.printStackTrace();
			System.out.println(e3.getMessage());
			Controller.getInstance().setDownloadMessage(e3.getMessage());
	        if ( stop ) { return; }
		} catch (Exception ex){
			ex.printStackTrace();
	        if ( stop ) { return; }
		}
		
		//done
		
        if ( stop ) { return; }
        final Stoppable ourProcessing = this;
        UiApplication.getUiApplication().invokeLater(new Runnable() {
            public void run() {
                if ( ourProcessing.isStopped() ) { return; }
            }
        });
	}
	
	public boolean stop() {
        if ( !stop ) {
            stop = true;
            synchronized(notifyObject) {
                notifyObject.notify();
            }
        }
        return true;
	}

	public boolean isStopped() {
        return stop;
	}

}
